package cn.edu.tju.elm.service;

import cn.edu.tju.core.model.User;
import cn.edu.tju.core.security.service.UserService;
import cn.edu.tju.elm.common.constants.RuleType;
import cn.edu.tju.elm.exception.DataNotFoundException;
import cn.edu.tju.elm.exception.ForbiddenException;
import cn.edu.tju.elm.exception.MethodArgumentNotValidException;
import cn.edu.tju.elm.model.DTO.WalletTransactionDTO;
import cn.edu.tju.elm.model.entity.*;
import cn.edu.tju.elm.repository.*;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.List;
import java.util.stream.Collectors;

@Service
@Transactional
@RequiredArgsConstructor
public class VirtualWalletService {

    private final VirtualWalletRepository virtualWalletRepository;
    private final WalletTransactionRepository walletTransactionRepository;
    private final RewardRuleRepository rewardRuleRepository;
    private final UserService userService;
    private final OrderRepository orderRepository;

    /**
     * 为用户创建钱包
     */
    public VirtualWallet createWalletForUser(User user) {
        if (virtualWalletRepository.existsByUserId(user.getId())) {
            throw new MethodArgumentNotValidException("用户已拥有钱包");
        }
        LocalDateTime now = LocalDateTime.now();

        VirtualWallet wallet = VirtualWallet.builder()
                .user(user)
                .balance(BigDecimal.ZERO)
                .frozenBalance(BigDecimal.ZERO)
                .overdraftLimit(BigDecimal.ZERO)
                .isVip(false)
                .createTime(now)
                .updateTime(now)
                .creator(user.getId())
                .updater(user.getId())
                .deleted(false)
                .build();

        return virtualWalletRepository.save(wallet);
    }

    /**
     * 获取当前用户的钱包
     */
    @Transactional(readOnly = true)
    public VirtualWallet getCurrentUserWallet() {
        User user = userService.getUserWithAuthorities();
        return virtualWalletRepository.findByUser(user)
                .orElseThrow(() -> new DataNotFoundException("钱包不存在"));
    }

    /**
     * 充值
     */
    public VirtualWallet recharge(BigDecimal amount, String remark) {
        User user = userService.getUserWithAuthorities();
        VirtualWallet wallet = getCurrentUserWallet();

        // 修复：使用新的查询方法，确保只返回一个规则
        RewardRule rechargeRule = rewardRuleRepository
                .findTopRechargeRuleByAmount(RuleType.RECHARGE, amount)
                .orElse(null);

        // 使用充血模型进行充值
        wallet.recharge(user, amount, rechargeRule);

        // 记录交易流水
        WalletTransaction transaction = WalletTransaction.createRecharge(user, wallet, amount, remark);
        walletTransactionRepository.save(transaction);

        return virtualWalletRepository.save(wallet);
    }

    /**
     * 提现
     */
    public VirtualWallet withdraw(BigDecimal amount, String remark) {
        User user = userService.getUserWithAuthorities();
        VirtualWallet wallet = getCurrentUserWallet();

        // 获取适用的提现手续费规则
        RewardRule withdrawRule = rewardRuleRepository
                .findByRuleTypeAndIsActiveTrue(RuleType.WITHDRAW)
                .stream()
                .findFirst()
                .orElse(null);

        // 使用充血模型进行提现
        wallet.withdraw(user, amount, withdrawRule);

        // 记录交易流水
        WalletTransaction transaction = WalletTransaction.createWithdraw(user, wallet, amount, remark);
        walletTransactionRepository.save(transaction);

        return virtualWalletRepository.save(wallet);
    }

    /**
     * 支付订单
     */
    public VirtualWallet payOrder(Long orderId) {
        User currentUser = userService.getUserWithAuthorities();
        VirtualWallet userWallet = getCurrentUserWallet();

        Order order = orderRepository.findById(orderId)
                .orElseThrow(() -> new DataNotFoundException("订单不存在"));

        if (!order.getCustomer().equals(currentUser)) {
            throw new ForbiddenException("只能支付自己的订单");
        }

        if (order.getOrderState() != 0) {
            throw new MethodArgumentNotValidException("订单状态不允许支付");
        }

        // 获取商家钱包
        VirtualWallet businessWallet = virtualWalletRepository.findByUserId(
                        order.getBusiness().getBusinessOwner().getId())
                .orElseThrow(() -> new MethodArgumentNotValidException("商家钱包不存在"));

        // 使用充血模型进行支付
        userWallet.transferTo(businessWallet, order.getOrderTotal());

        LocalDateTime now = LocalDateTime.now();
        userWallet.setUpdateTime(now);
        businessWallet.setUpdateTime(now);

        // 冻结商家资金（等待确认收货）
        businessWallet.freeze(order.getOrderTotal());
        businessWallet.setUpdateTime(now);

        // 更新订单状态
        order.setOrderState(1); // 已支付
        order.setUpdateTime(now);

        // 记录交易流水
        WalletTransaction transaction = WalletTransaction.createPayment(
                currentUser, userWallet, businessWallet, order.getOrderTotal(), order, "订单支付");
        walletTransactionRepository.save(transaction);

        virtualWalletRepository.save(businessWallet);
        orderRepository.save(order);

        return virtualWalletRepository.save(userWallet);
    }

    /**
     * 确认收货，解冻商家资金
     */
    public void confirmOrder(Long orderId) {
        User currentUser = userService.getUserWithAuthorities();
        Order order = orderRepository.findById(orderId)
                .orElseThrow(() -> new DataNotFoundException("订单不存在"));

        if (!order.getCustomer().equals(currentUser)) {
            throw new ForbiddenException("只能确认自己的订单");
        }

        if (order.getOrderState() != 1) {
            throw new MethodArgumentNotValidException("订单状态不允许确认收货");
        }

        // 获取商家钱包
        VirtualWallet businessWallet = virtualWalletRepository.findByUserId(
                        order.getBusiness().getBusinessOwner().getId())
                .orElseThrow(() -> new MethodArgumentNotValidException("商家钱包不存在"));

        // 解冻资金
        businessWallet.unfreeze(order.getOrderTotal());
        businessWallet.setUpdateTime(LocalDateTime.now());

        // 更新订单状态
        order.setOrderState(2); // 已送达
        order.setUpdateTime(LocalDateTime.now());

        // 记录交易流水
        WalletTransaction transaction = WalletTransaction.createUnfreeze(currentUser,order,businessWallet);
        walletTransactionRepository.save(transaction);

        virtualWalletRepository.save(businessWallet);
        orderRepository.save(order);
    }

    /**
     * 查询交易流水
     */
    @Transactional(readOnly = true)
    public List<WalletTransactionDTO> getTransactionHistory() {
        VirtualWallet wallet = getCurrentUserWallet();
        List<WalletTransaction> transactions = walletTransactionRepository.findByWalletId(wallet.getId());
        return transactions.stream()
                .map(WalletTransactionDTO::convertToDTO)
                .collect(Collectors.toList());
    }

    /**
     * 设置透支额度
     */
    public VirtualWallet setOverdraftLimit(BigDecimal limit) {
        User user = userService.getUserWithAuthorities();
        VirtualWallet wallet = getCurrentUserWallet();

        wallet.setOverdraftLimit(limit);
        wallet.setUpdateTime(LocalDateTime.now());
        wallet.setUpdater(user.getId());

        return virtualWalletRepository.save(wallet);
    }

    /**
     * 升级为VIP用户
     */
    public VirtualWallet upgradeToVip() {
        VirtualWallet wallet = getCurrentUserWallet();

        if (wallet.getIsVip()) {
            throw new MethodArgumentNotValidException("您已经是VIP用户");
        }

        // 升级为VIP，设置透支额度为1000元
        wallet.upgradeToVip(BigDecimal.valueOf(1000));
        wallet.setUpdateTime(LocalDateTime.now());

        return virtualWalletRepository.save(wallet);
    }

    /**
     * 检查用户是否为VIP
     */
    @Transactional(readOnly = true)
    public boolean isVipUser() {
        VirtualWallet wallet = getCurrentUserWallet();
        return wallet.getIsVip();
    }
}